package com.weimob.mcloud.wechatwork.customer.mq.handler.customerprocess;

import com.alibaba.fastjson.JSON;
import com.weimob.arch.artemis.client.api.consume.ArtemisMessage;
import com.weimob.arch.artemis.client.api.consume.ArtemisMessages;
import com.weimob.arch.artemis.client.spring.annotation.ArtemisMessageListener;
import com.weimob.arch.artemis.client.spring.annotation.Subscribe;
import com.weimob.arch.sub.env.application.annotation.SubEnvExposePoint;
import com.weimob.arch.sub.env.application.annotation.SubEnvTagExtractor;
import com.weimob.dq.client.annotation.DqListener;
import com.weimob.dq.core.entity.MsgPoolEntity;
import com.weimob.mcloud.wechatwork.common.utils.JsonUtil;
import com.weimob.mcloud.wechatwork.core.base.MultiResponse;
import com.weimob.mcloud.wechatwork.core.base.SingleRequest;
import com.weimob.mcloud.wechatwork.core.entity.base.PrivateSphereRelation;
import com.weimob.mcloud.wechatwork.core.entity.config.clue.ClueCfg;
import com.weimob.mcloud.wechatwork.core.entity.privatesphere.PrivateSphere;
import com.weimob.mcloud.wechatwork.core.entity.relation.customer.CustomerProcess;
import com.weimob.mcloud.wechatwork.core.entity.relation.customer.CustomerStage;
import com.weimob.mcloud.wechatwork.core.entity.relation.customer.CustomerStageRelation;
import com.weimob.mcloud.wechatwork.core.entity.relation.customer.CustomerStageRemindRecord;
import com.weimob.mcloud.wechatwork.core.entity.relation.employee.Department;
import com.weimob.mcloud.wechatwork.core.entity.relation.employee.Employee;
import com.weimob.mcloud.wechatwork.core.enums.customer.ProcessStatusEnum;
import com.weimob.mcloud.wechatwork.core.enums.employee.EmployeeActiveStatusEnum;
import com.weimob.mcloud.wechatwork.core.enums.employee.EmployeeStatusEnum;
import com.weimob.mcloud.wechatwork.core.service.customer.CustomerProcessService;
import com.weimob.mcloud.wechatwork.core.service.customer.CustomerStageRelationService;
import com.weimob.mcloud.wechatwork.core.service.customer.CustomerStageRemindRecordService;
import com.weimob.mcloud.wechatwork.core.service.customer.request.GetSingleCustomerProcessRequest;
import com.weimob.mcloud.wechatwork.core.service.customer.request.QueryListRemindRecordRequest;
import com.weimob.mcloud.wechatwork.core.service.customer.request.SaveRemindRecordRequest;
import com.weimob.mcloud.wechatwork.core.service.customer.request.UpdateRemindRecordRequest;
import com.weimob.mcloud.wechatwork.core.service.customer.response.GetSingleCustomerProcessResponse;
import com.weimob.mcloud.wechatwork.core.service.employee.EmployeeService;
import com.weimob.mcloud.wechatwork.core.service.privatesphere.PrivateSphereService;
import com.weimob.mcloud.wechatwork.customer.config.DqConfig;
import com.weimob.mcloud.wechatwork.customer.convertor.customer.CustomerProcessRequestBuilder;
import com.weimob.mcloud.wechatwork.customer.domain.ArtemisBaseInfo;
import com.weimob.mcloud.wechatwork.customer.domain.ArtemisConstant;
import com.weimob.mcloud.wechatwork.customer.domain.CustomerRemindMsgDTO;
import com.weimob.mcloud.wechatwork.customer.externalDependencyProxy.usermanagement.EmployeeProxy;
import com.weimob.mcloud.wechatwork.customer.listener.event.CustomerStageRemindEvent;
import com.weimob.mcloud.wechatwork.customer.service.MsgNoticeService;
import com.weimob.mcloud.wechatwork.customer.service.impl.ArtemisService;
import com.weimob.soa.common.response.SoaResponse;
import com.weimob.soa.common.string.StringUtil;
import com.weimob.soa.common.utils.SoaUtil;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import javax.annotation.Resource;
import java.util.*;
import java.util.stream.Collectors;

/**
 * @author jiawei.you01
 * @date 2022/9/22 17:47
 * @since 1.0
 */
@Slf4j
@Component
public class CustomerStageRemindHandler {

    @Autowired
    CustomerStageRelationService customerStageRelationService;

    @Autowired
    CustomerStageRemindRecordService remindRecordService;

    @Autowired
    CustomerProcessService customerProcessService;

    @Resource
    CustomerProcessRequestBuilder requestBuilder;

    @Autowired
    EmployeeService employeeService;

    @Autowired
    PrivateSphereService privateSphereService;

    @Autowired
    MsgNoticeService msgNoticeService;

    @Autowired
    private EmployeeProxy employeeProxy;

    @Autowired
    private ArtemisService artemisService;

    @DqListener(topic = DqConfig.CUSTOMER_STAGE_REMIND)
    public void customerStageNoticeHandlerHacker(MsgPoolEntity msgPoolEntity) {
        if (null == msgPoolEntity) {
            return;
        }

        CustomerStageRemindEvent customerStageRemindEvent = getPushDqQueueModel(msgPoolEntity);
        if (null == customerStageRemindEvent) {
            log.error("CustomerStageRemindEvent is null. MsgPoolEntity:{}", JSON.toJSONString(msgPoolEntity));
            return;
        }
        if (StringUtils.isBlank(customerStageRemindEvent.getPrivateSphereId())) {
            log.error("CustomerStageRemindEvent is illegal. CustomerStageRemindEvent:{}", JSON.toJSONString(customerStageRemindEvent));
            return;
        }

        PrivateSphere soaRequest = new PrivateSphere();
        soaRequest.setPrivateSphereId(customerStageRemindEvent.getPrivateSphereId());
        SoaResponse<PrivateSphere, Void> soaResponse;
        try {
            soaResponse = this.privateSphereService.fetch(soaRequest);
        } catch (Exception e) {
            log.error("PrivateSphereService.fetch error. SoaRequest:{} errorMessage:{}", JSON.toJSONString(soaRequest), e.getMessage());
            throw e;
        }
        if (null == soaResponse || null == soaResponse.getResponseVo()) {
            log.warn("SoaResponse is illegal. SoaRequest:{} SoaResponse:{}", JSON.toJSONString(soaRequest), JSON.toJSONString(soaResponse));
            return;
        }
        if (null == soaResponse.getResponseVo().getBosId()) {
            log.error("PrivateSphere is illegal. PrivateSphere:{}", JSON.toJSONString(soaResponse.getResponseVo()));
            return;
        }

        this.push(soaResponse.getResponseVo().getBosId(), msgPoolEntity);
    }

    /**
     * 将延迟队列消息打上灰度标，原样推送至Artemis
     *
     * 延迟队列的间接灰度方案使用，当延迟队列支持灰度后，可直接消费延迟队列
     */
    @SubEnvExposePoint
    @SubEnvTagExtractor(key = "weimob-bosid", value = "#args[0]")
    public void push(long bosId, MsgPoolEntity msgPoolEntity) {
        ArtemisBaseInfo<MsgPoolEntity> artemisBaseInfo = new ArtemisBaseInfo<>();
        artemisBaseInfo.setTopic(DqConfig.CUSTOMER_STAGE_REMIND);
        artemisBaseInfo.setProducer(ArtemisConstant.USER);
        artemisBaseInfo.setEvent(msgPoolEntity);

        boolean success = this.artemisService.sendToArtemis(artemisBaseInfo);
        if (success) {
            log.info("ArtemisProducer send message success. bosId:{} ArtemisBaseInfo:{}", bosId, JSON.toJSONString(artemisBaseInfo));
        }
    }

    /**
     * 接收带灰度标的Artemis消息，并调用原延迟队列处理方法
     *
     * 延迟队列的间接灰度方案使用，当延迟队列支持灰度后，可直接消费延迟队列
     */
    @ArtemisMessageListener(value = @Subscribe(topic = DqConfig.CUSTOMER_STAGE_REMIND, user = ArtemisConstant.CONSUMER_USER))
    public void pull(ArtemisMessages artemisMessages) {
        if (CollectionUtils.isEmpty(artemisMessages)) {
            return;
        }

        for (ArtemisMessage artemisMessage : artemisMessages) {
            if (null == artemisMessage) {
                continue;
            }

            this.customerStageNoticeHandler(JSON.parseObject(artemisMessage.getValue(), MsgPoolEntity.class));
        }
    }

    public void customerStageNoticeHandler(MsgPoolEntity msgClientEntity) {
        CustomerStageRemindEvent remindEvent = getPushDqQueueModel(msgClientEntity);
        if (Objects.isNull(remindEvent)) {
            log.error("customerStageNoticeHandler.remindEvent is null");
            return;
        }

        log.info("准备发送跟进提醒:{}", JsonUtil.obj2Str(remindEvent));
        SingleRequest<CustomerStageRelation> request = buildFetchStageRelation(remindEvent);
        SoaResponse<MultiResponse<CustomerStageRelation>, ?> singleResponse = customerStageRelationService.fetchToFollowList(request);

        List<CustomerStageRelation> customerStageRelationList = SoaUtil.unpack(singleResponse).getDataList();
        if (CollectionUtils.isEmpty(customerStageRelationList)) {
            log.info("未找到没有跟进的员工:{},stageId:{}", remindEvent.getEmployeeId(), remindEvent.getStageId());
            return;
        }

        customerStageRelationList = customerStageRelationList.stream().filter(i -> !i.getHasEnd()).collect(Collectors.toList());

        if (CollectionUtils.isEmpty(customerStageRelationList)) {
            log.info("所有客户都处于终态,员工{},stageId:{}", remindEvent.getEmployeeId(), remindEvent.getStageId());
            return;
        }

        CustomerStageRelation customerStageRelation = customerStageRelationList.get(0);

        if (customerStageRelation == null || StringUtil.isNotEmpty(customerStageRelation.getRemark()) || customerStageRelation.getHasEnd()) {
            log.error("即将发送跟进提醒，但是找不到customerStageRelation或者跟进提醒已填写或者当前为终态,event:{}", JsonUtil.obj2Str(remindEvent));
            return;
        }

        PrivateSphere privateSphere = new PrivateSphere();
        privateSphere.setPrivateSphereId(remindEvent.getPrivateSphereId());
        SoaResponse<PrivateSphere, Void> fetch = privateSphereService.fetch(privateSphere);
        privateSphere = SoaUtil.unpack(fetch);

        //构建参数
        SingleRequest<GetSingleCustomerProcessRequest> singleRequest = requestBuilder.buildGetSingleRequest(privateSphere, null, remindEvent.getProcessId());


        SoaResponse<GetSingleCustomerProcessResponse, Void> single = customerProcessService.getSingle(singleRequest);
        CustomerProcess customerProcess = SoaUtil.unpack(single).getCustomerProcess();

        if (ProcessStatusEnum.VALID.equals(customerProcess.getStatusEnum())) {
            log.info("流程已关闭,processName:{},processId:{}", customerProcess.getProcessName(), customerProcess.getProcessId());
            return;
        }

        CustomerStage stage = customerProcess.getCustomerStages()
                .stream()
                .filter(i -> i.getStageId().equals(remindEvent.getStageId()))
                .findAny().orElse(null);
        if (stage == null) {
            log.info("未找到stage,event:{}", JsonUtil.obj2Str(remindEvent));
            return;
        }
        ClueCfg clueCfg = stage.getCfgList()
                .stream()
                .filter(i -> i.getPotentialSettingEnum().equals(remindEvent.getSettingEnum()))
                .findAny()
                .orElse(null);
        if (clueCfg == null || !clueCfg.getRuleOpenFlag()) {
            log.info("当前提醒规则已关闭，无需发送提醒,员工:{},stageId:{}", remindEvent.getEmployeeId(), remindEvent.getStageId());
            return;
        }


       /* //获取最新的跟进时间
        long relationTime = customerStageRelation.getUpdateTime().getTime();
        long remindTime = calculateClueCfgTime(clueCfg);

        if ((System.currentTimeMillis() - relationTime) < remindTime) {
            log.info("未到提醒时间,忽略,员工:{},stageId:{}",remindEvent.getEmployeeId(),remindEvent.getStageId());
            return;
        }*/


        List<String> authEmployeeIdList = customerProcess
                .getEmployees()
                .stream()
                .map(PrivateSphereRelation::getId)
                .collect(Collectors.toList());
        List<String> authDepartmentIdList = customerProcess
                .getDepartments()
                .stream()
                .map(PrivateSphereRelation::getId)
                .collect(Collectors.toList());


        Employee employee = customerStageRelation.getEmployee();

        employee = employeeProxy.fetchEmployeeById(privateSphere, employee.getTxUserId(), employee.getId());
        if (Objects.isNull(employee)) {
            log.error("customerStageNoticeHandler.employee is null");
            return;
        }
        EmployeeStatusEnum status = employee.getStatus();
        EmployeeActiveStatusEnum activeStatus = employee.getActiveStatus();
        if (EmployeeActiveStatusEnum.INACTIVE.equals(activeStatus) || EmployeeStatusEnum.USER_UN_AUTHORIZATION.equals(status)) {
            log.warn("customerStageNoticeHandler 员工无坐席或者无授权！员工:{},stageId:{}", remindEvent.getEmployeeId(), remindEvent.getStageId());
            return;
        }
        List<String> departmentCodeList = employee.getDepartments().stream().map(Department::getDepartmentCode).collect(Collectors.toList());
        List<String> departmentIdList = new ArrayList<>();
        if (CollectionUtils.isNotEmpty(departmentCodeList)) {
            for (String departmentCode : departmentCodeList) {
                String[] split = departmentCode.split("_");
                departmentIdList.addAll(Arrays.asList(split));
            }
        }

        if (!authEmployeeIdList.contains(employee.getId()) &&
                Collections.disjoint(departmentIdList, authDepartmentIdList)) {
            log.info("员工未在可见范围,employeeId:{},processId:{}", employee.getId(), customerProcess.getProcessId());
            return;
        }

        //发送提醒
        CustomerRemindMsgDTO msgDTO = new CustomerRemindMsgDTO();
        msgDTO.setStageId(stage.getStageId());
        msgDTO.setStageName(stage.getStageName());
        msgDTO.setTxUserId(employee.getTxUserId());
        msgDTO.setClueCfg(clueCfg);
        msgDTO.setPrivateSphere(privateSphere);
        msgNoticeService.customerRemindNotice(msgDTO);
        log.info("给员工发送了跟进提醒,员工:{},stageId:{}", remindEvent.getEmployeeId(), remindEvent.getStageId());


        QueryListRemindRecordRequest queryListRemindRecordRequest = new QueryListRemindRecordRequest();
        queryListRemindRecordRequest.setStageId(remindEvent.getStageId());
        queryListRemindRecordRequest.setEmployeeIdList(Collections.singletonList(remindEvent.getEmployeeId()));
        SoaResponse<MultiResponse<CustomerStageRemindRecord>, Void> multiResponseVoidSoaResponse = remindRecordService.queryList(queryListRemindRecordRequest);
        List<CustomerStageRemindRecord> dataList = SoaUtil.unpack(multiResponseVoidSoaResponse).getDataList();

        if (CollectionUtils.isEmpty(dataList)) {
            CustomerStageRemindRecord remindRecord = buildNewCustomerStageRemindRecord(remindEvent, clueCfg);
            SaveRemindRecordRequest saveRemindRecordRequest = new SaveRemindRecordRequest();
            saveRemindRecordRequest.setRemindRecord(remindRecord);
            remindRecordService.save(saveRemindRecordRequest);
        } else {
            CustomerStageRemindRecord remindRecord = dataList.get(0);
            remindRecord.setLatestRecordTime(new Date());
            UpdateRemindRecordRequest updateRemindRecordRequest = new UpdateRemindRecordRequest();
            updateRemindRecordRequest.setRemindRecord(remindRecord);
            remindRecordService.update(updateRemindRecordRequest);
        }

    }


    private CustomerStageRemindRecord buildNewCustomerStageRemindRecord(CustomerStageRemindEvent remindEvent, ClueCfg clueCfg) {
        CustomerStageRemindRecord remindRecord = new CustomerStageRemindRecord();
        Employee employee = new Employee();
        employee.setId(remindEvent.getEmployeeId());
        remindRecord.setEmployee(employee);

        CustomerStage stage = new CustomerStage();
        stage.setStageId(remindEvent.getStageId());
        remindRecord.setCustomerStage(stage);

        CustomerProcess process = new CustomerProcess();
        process.setProcessId(remindEvent.getProcessId());
        remindRecord.setProcess(process);

        remindRecord.setClueCfg(clueCfg);
        PrivateSphere privateSphere = new PrivateSphere();
        privateSphere.setPrivateSphereId(remindEvent.getPrivateSphereId());
        remindRecord.setPrivateSphere(privateSphere);

        return remindRecord;
    }

    private SingleRequest<CustomerStageRelation> buildFetchStageRelation(CustomerStageRemindEvent remindEvent) {
        SingleRequest<CustomerStageRelation> singleRequest = new SingleRequest<>();
        CustomerStageRelation relation = new CustomerStageRelation();
        relation.setCustomerProcess(relation.toProcess(remindEvent.getProcessId()));
        relation.setCustomerStage(relation.toCustomerStage(remindEvent.getStageId()));
        relation.setPrivateSphereId(remindEvent.getPrivateSphereId());
        Employee employee = new Employee();
        employee.setId(remindEvent.getEmployeeId());
        relation.setEmployee(employee);
        relation.setCurrentStage(true);
        singleRequest.setData(relation);
        return singleRequest;
    }

    /**
     * 获取延迟队列消息并对象转换
     */
    private CustomerStageRemindEvent getPushDqQueueModel(MsgPoolEntity msgClientEntity) {
        String body = msgClientEntity.getBody();
        if (org.apache.commons.lang3.StringUtils.isBlank(body)) {
            return null;
        }
        CustomerStageRemindEvent remindEvent;
        try {
            remindEvent = JSON.parseObject(body, CustomerStageRemindEvent.class);
        } catch (Exception e) {
            log.error("handlerConsumer json parse fail,msgClientEntity:{},case by:{}", JSON.toJSONString(msgClientEntity), e.getMessage());
            return null;
        }
        return remindEvent;
    }

    private long calculateClueCfgTime(ClueCfg clueCfg) {
        return Long.parseLong(clueCfg.getRuleValue()) * 24 * 60 * 60 * 1000;
    }

}
